package com.ilikesoup.instant.executor;

import java.util.Collection;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;

public interface KeyPickRunnable<K> extends Runnable {
    /**
     * 获取互斥键的集合
     *
     * 如果集合中的任意键所属的任务正在中，则需等待它们执行完成。
     *
     * @return
     */
    Collection<K> getKeys();

    static <K> KeyPickRunnable<K> create(Collection<K> keys, Runnable runnable) {
        return new PlainKeyPickRunnable<>(keys, runnable);
    }

    static <T, K> KeyPickRunnable<K> create(T target, Function<T, Collection<K>> keyGetter, Consumer<T> consumer) {
        return new SimpleKeyPickRunnable<>(target, keyGetter.apply(target), consumer);
    }

    static <T, K> KeyPickRunnable<K> create(T target, Collection<K> keys, Consumer<T> consumer) {
        return new SimpleKeyPickRunnable<>(target, keys, consumer);
    }

    class SimpleKeyPickRunnable<T, K> implements KeyPickRunnable<K> {
        private final Consumer<T> consumer;
        private final Collection<K> keys;
        private final T target;

        private SimpleKeyPickRunnable(T target, Collection<K> keys, Consumer<T> consumer) {
            this.target = Objects.requireNonNull(target);
            this.keys = keys;
            this.consumer = Objects.requireNonNull(consumer);
        }

        @Override
        public Collection<K> getKeys() {
            return keys;
        }

        @Override
        public void run() {
            consumer.accept(target);
        }
    }

    class PlainKeyPickRunnable<K> implements KeyPickRunnable<K> {

        private final Collection<K> keys;
        private final Runnable runnable;

        PlainKeyPickRunnable(Collection<K> keys, Runnable runnable) {
            this.keys = keys;
            this.runnable = runnable;
        }

        @Override
        public Collection<K> getKeys() {
            return keys;
        }

        @Override
        public void run() {
            runnable.run();
        }
    }

}
